{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "76f3d0b5",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "#  11\\.  梯度下降法实现与应用  # \n",
    "\n",
    "##  11.1.  介绍  # \n",
    "\n",
    "逻辑回归实验中，我们学会使用梯度下降方法求解。梯度下降作为一种最优化方法，可以普遍用于参数问题的优化过程中。为了更好地体会这种方法的优点和了解其使用过程，本次挑战中将尝试使用梯度下降解决前面学习过的线性回归问题。 \n",
    "\n",
    "##  11.2.  知识点  # \n",
    "\n",
    "  * 最小二乘法求解线性回归参数 \n",
    "\n",
    "  * 梯度下降法求解线性回归参数 \n",
    "\n",
    "还记得学习过的「线性回归」吗？我们使用了普通最小二乘法 OLS 来求解线性回归拟合参数。当然，根据不同的计算方法，OLS 又可以分为代数求解和矩阵求解。 \n",
    "\n",
    "首先，我们复习一下线性回归普通最小二乘法代数求解过程。对于一元线性方程： \n",
    "\n",
    "$$ y ( x , w ) = w _ { 0 } + w _ { 1 } x \\tag{1} $$ \n",
    "\n",
    "定义其平方损失函数为： \n",
    "\n",
    "$$ f = \\sum _ { i = 1 } ^ { n } \\left( y _ { i } - \\left( w _ { 0 } + w _ { 1 } x _ { i } \\right) \\right) ^ { 2 } \\tag{2} $$ \n",
    "\n",
    "接下来，求平方损失函数 1 阶偏导数： \n",
    "\n",
    "$$ \\frac { \\partial f } { \\partial w _ { 0 } } = - 2 \\sum _ { i = 1 } ^ { n } \\left( y _ { i } - \\left( w _ { 0 } + w _ { 1 } x _ { i } \\right) \\right) \\tag{3a} $$ \n",
    "\n",
    "$$ \\frac { \\partial f } { \\partial w _ { 1 } } = -2 \\sum _ { i = 1 } ^ { n } x _ { i } \\left( y _ { i } - \\left( w _ { 0 } + w _ { 1 } x _ { i } \\right) \\right) \\tag{3b} $$ \n",
    "\n",
    "为了求出  $w_0$  和  $w_1$  的值, 我们令  $\\frac{\\partial f}{\\partial w_{0}}=0$  以及  $\\frac{\\partial f}{\\partial w_{1}}=0$  ，解得： \n",
    "\n",
    "$$\\begin{align*} w_0 &= \\frac{\\sum_{i=1}^n x_i^2 \\sum_{i=1}^n y_i - \\sum_{i=1}^n x_i \\sum_{i=1}^n x_iy_i}{n\\sum_{i=1}^n x_i^2 - \\left(\\sum_{i=1}^n x_i\\right)^2} \\tag{4a} \\\\\\ w_1 &= \\frac{n\\sum_{i=1}^n x_iy_i - \\sum_{i=1}^n x_i \\sum_{i=1}^n y_i}{n\\sum_{i=1}^n x_i^2 - \\left(\\sum_{i=1}^n x_i\\right)^2} \\tag{4b} \\end{align*}$$ \n",
    "\n",
    "补充公式 3 → 4 详细求解过程 \n",
    "\n",
    "我们从等式(3a)和(3b)开始: \n",
    "\n",
    "$$\\begin{split} \\begin{align} \\frac{\\partial f}{\\partial w_0} &= -2\\sum_{i=1}^{n}(y_i - (w_0 + w_1x_i)) = 0 \\tag{3a}\\\\\\ \\frac{\\partial f}{\\partial w_1} &= -2\\sum_{i=1}^{n}x_i(y_i - (w_0 + w_1x_i)) = 0 \\tag{3b} \\end{align} \\end{split}$$ \n",
    "\n",
    "将等式(3a)的右边等于0,可以得到: \n",
    "\n",
    "$$ \\sum_{i=1}^{n}y_i - nw_0 - w_1\\sum_{i=1}^{n}x_i = 0 \\tag{5} $$ \n",
    "\n",
    "将等式(3b)的右边等于0,可以得到: \n",
    "\n",
    "$$ \\sum_{i=1}^{n}x_iy_i - w_0\\sum_{i=1}^{n}x_i^2 - w_1\\sum_{i=1}^{n}x_i^2 = 0 \\tag{6} $$ \n",
    "\n",
    "我们现在有两个方程(5)和(6),包含两个未知数  $w_0$  和  $w_1$  。通过代数运算,我们可以解出  $w_0$  和  $w_1$  的表达式。 \n",
    "\n",
    "首先,将方程(5)中的  $w_1$  表达式代入方程(6): \n",
    "\n",
    "$$\\begin{split} \\begin{align} \\sum_{i=1}^{n}x_iy_i -\n",
    "                        w_0\\sum_{i=1}^{n}x_i^2 -\n",
    "                        \\left(\\frac{1}{n}\\sum_{i=1}^{n}y_i -\n",
    "                        \\frac{w_0}{n}\\sum_{i=1}^{n}x_i\\right)\\sum_{i=1}^{n}x_i^2\n",
    "                        &= 0\\\\ \\sum_{i=1}^{n}x_iy_i - w_0\\sum_{i=1}^{n}x_i^2\n",
    "                        - \\frac{1}{n}\\sum_{i=1}^{n}x_i^2\\sum_{i=1}^{n}y_i +\n",
    "                        \\frac{w_0}{n}\\left(\\sum_{i=1}^{n}x_i\\right)^2 &= 0\\\\\n",
    "                        \\therefore w_0 &=\n",
    "                        \\frac{\\sum_{i=1}^{n}x_i^2\\sum_{i=1}^{n}y_i -\n",
    "                        \\sum_{i=1}^{n}x_i\\sum_{i=1}^{n}x_iy_i}{n\\sum_{i=1}^{n}x_i^2\n",
    "                        - \\left(\\sum_{i=1}^{n}x_i\\right)^2} \\tag{4a} \\end{align}\n",
    "                        \\end{split}$$ \n",
    "\n",
    "代入等式(5),我们可以得到  $w_1$  的表达式: \n",
    "\n",
    "$$\\begin{split} \\begin{align} \\sum_{i=1}^{n}y_i -\n",
    "                        n\\left(\\frac{\\sum_{i=1}^{n}x_i^2\\sum_{i=1}^{n}y_i -\n",
    "                        \\sum_{i=1}^{n}x_i\\sum_{i=1}^{n}x_iy_i}{n\\sum_{i=1}^{n}x_i^2\n",
    "                        - \\left(\\sum_{i=1}^{n}x_i\\right)^2}\\right) -\n",
    "                        w_1\\sum_{i=1}^{n}x_i &= 0\\\\ \\therefore w_1 &=\n",
    "                        \\frac{n\\sum_{i=1}^{n}x_iy_i -\n",
    "                        \\sum_{i=1}^{n}x_i\\sum_{i=1}^{n}y_i}{n\\sum_{i=1}^{n}x_i^2\n",
    "                        - \\left(\\sum_{i=1}^{n}x_i\\right)^2} \\tag{4b} \\end{align}\n",
    "                        \\end{split}$$ \n",
    "\n",
    "至此，我们就用代数的方式求解出线性方程的参数了。下面使用 Python 代码实现 OLS 代数求解函数。 \n",
    "\n",
    "Exercise 11.1 \n",
    "\n",
    "挑战：根据公式 (4) 完成普通最小二乘法代数计算函数。 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2a4fe43c",
   "metadata": {},
   "outputs": [],
   "source": [
    "def ols_algebra(x, y):\n",
    "    \"\"\"\n",
    "    参数:\n",
    "    x -- 自变量数组\n",
    "    y -- 因变量数组\n",
    "\n",
    "    返回:\n",
    "    w1 -- 线性方程系数\n",
    "    w0 -- 线性方程截距项\n",
    "    \"\"\"\n",
    "\n",
    "    ### 代码开始 ### (≈ 3 行代码)\n",
    "    w1 = None\n",
    "    w0 = None\n",
    "    ### 代码结束 ###\n",
    "\n",
    "    return w1, w0"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7d8f287e",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "参考答案  Exercise 11.1 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "eee8ffa0",
   "metadata": {},
   "outputs": [],
   "source": [
    "def ols_algebra(x, y):\n",
    "    \"\"\"\n",
    "    参数:\n",
    "    x -- 自变量数组\n",
    "    y -- 因变量数组\n",
    "\n",
    "    返回:\n",
    "    w1 -- 线性方程系数\n",
    "    w0 -- 线性方程截距项\n",
    "    \"\"\"\n",
    "\n",
    "    ### 代码开始 ### (≈ 3 行代码)\n",
    "    n = len(x)\n",
    "    w1 = (n*sum(x*y) - sum(x)*sum(y))/(n*sum(x*x) - sum(x)*sum(x))\n",
    "    w0 = (sum(x*x)*sum(y) - sum(x)*sum(x*y))/(n*sum(x*x)-sum(x)*sum(x))\n",
    "    ### 代码结束 ###\n",
    "\n",
    "    return w1, w0"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "06c206cc",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "下面，我们提供一组测试数据。 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "bbf4e56a",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "x = np.array([55, 71, 68, 87, 101, 87, 75, 78, 93, 73])\n",
    "y = np.array([91, 101, 87, 109, 129, 98, 95, 101, 104, 93])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ed67c62f",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "运行测试 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "462a6612",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(np.float64(0.718), np.float64(44.256))"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "w1, w0 = ols_algebra(x, y)\n",
    "round(w1, 3), round(w0, 3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "63aaf52e",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "期望输出 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "a99640ea",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.718, 44.256)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "(0.718, 44.256)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4b3da289",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "至此，我们得到了最终计算结果： \n",
    "\n",
    "$$ y=0.718∗x+44.256 $$ \n",
    "\n",
    "线性回归问题除了可以使用普通最小二乘法求解之外，实际上还可以使用迭代法求解。这里，我们可以应用逻辑回归实验中学习到的梯度下降方法来求解线性回归问题。 \n",
    "\n",
    "我们依旧沿用上面的平方损失函数。那么当使用迭代法时，只需要修改一个步骤。也就是不再令  $\\frac{\\partial f}{\\partial w_{0}}=0$  以及  $\\frac{\\partial f}{\\partial w_{1}}=0$  ，而是使用梯度下降法求解参数： \n",
    "\n",
    "$$ w _ { 0 } = w _ { 0 } - l r * \\frac { \\partial f } { \\partial w _ { 0 } } \\tag{5a} $$ \n",
    "\n",
    "$$ w _ { 1 } = w _ { 1 } - l r * \\frac { \\partial f } { \\partial w _ { 1 } } \\tag{5b} $$ \n",
    "\n",
    "下面使用 Python 代码实现梯度下降法求解过程。 \n",
    "\n",
    "Exercise 11.2 \n",
    "\n",
    "挑战：根据公式 (3) 和公式 (5) 完成普通最小二乘法代数计算函数。 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7f309747",
   "metadata": {},
   "outputs": [],
   "source": [
    "def ols_gradient_descent(x, y, lr, num_iter):\n",
    "    \"\"\"\n",
    "    参数:\n",
    "    x -- 自变量数组\n",
    "    y -- 因变量数组\n",
    "    lr -- 学习率\n",
    "    num_iter -- 迭代次数\n",
    "\n",
    "    返回:\n",
    "    w1 -- 线性方程系数\n",
    "    w0 -- 线性方程截距项\n",
    "    \"\"\"\n",
    "\n",
    "    ### 代码开始 ### (> 5 行代码)\n",
    "    w1 = None\n",
    "    w0 = None\n",
    "    ### 代码结束 ###\n",
    "\n",
    "    return w1, w0"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7461a35f",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "参考答案  Exercise 11.2 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "1e0e8ed1",
   "metadata": {},
   "outputs": [],
   "source": [
    "def ols_gradient_descent(x, y, lr, num_iter):\n",
    "    \"\"\"\n",
    "    参数:\n",
    "    x -- 自变量数组\n",
    "    y -- 因变量数组\n",
    "    lr -- 学习率\n",
    "    num_iter -- 迭代次数\n",
    "\n",
    "    返回:\n",
    "    w1 -- 线性方程系数\n",
    "    w0 -- 线性方程截距项\n",
    "    \"\"\"\n",
    "\n",
    "    ### 代码开始 ### (> 5 行代码)\n",
    "\n",
    "    w1 = 0  # 初始参数为 0\n",
    "    w0 = 0  # 初始参数为 0\n",
    "\n",
    "    for i in range(num_iter):  # 梯度下降迭代\n",
    "        # 计算近似值\n",
    "        y_hat = (w1 * x) + w0\n",
    "        # 计算参数对应梯度\n",
    "        w1_gradient = -2 * sum(x * (y - y_hat))\n",
    "        w0_gradient = -2 * sum(y - y_hat)\n",
    "        # 根据梯度更新参数\n",
    "        w1 -= lr * w1_gradient\n",
    "        w0 -= lr * w0_gradient\n",
    "\n",
    "    ### 代码结束 ###\n",
    "\n",
    "    return w1, w0"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "50c0a848",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "运行测试 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "843c7d46",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(np.float64(1.264), np.float64(0.038))"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "w1_, w0_ = ols_gradient_descent(x, y, lr=0.00001, num_iter=100)\n",
    "round(w1_, 3), round(w0_, 3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "62f041c8",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "期望输出 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "6b015326",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1.264, 0.038)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "(1.264, 0.038)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1d7bf67a",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "至此，我们得到了最终计算结果： \n",
    "\n",
    "$$ y=1.264∗x+0.038 $$ \n",
    "\n",
    "你会发现迭代法和我们上面使用 OLS 计算的精确解有一些出入。实际上主要是截距项的差异，不过截距项对线性方程的影响较小。我们可以通过绘图来对比两种方法拟合效果。 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "d68e4a28",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 1.0, 'Gradient descent')"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAABMIAAAHDCAYAAADGE7aiAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAAhaVJREFUeJzt3QmcTfUbx/HvzFizjKWEoiTFRIRI+bdRlpJKC1HKli2JJBVSSrQosmQpla0UikpZKim7yNaiJLsiY8t+/6/n/JrJjMGMWc69cz/v1+s28zvnzPW71zTz85zn9zwRgUAgIAAAAAAAACCTi/R7AgAAAAAAAEBGIBAGAAAAAACAsEAgDAAAAAAAAGGBQBgAAAAAAADCAoEwAAAAAAAAhAUCYQAAAAAAAAgLBMIAAAAAAAAQFgiEAQAAAAAAICwQCAMAAAAAAEBYIBAGAAAAADip+++/X+eff36CYxEREXr66acVCkJprgDSF4EwAEFv5cqVatKkic455xxlz55dRYsWVePGjb3jxxo1apS3yFm0aNFJn+/PP//Uww8/rNKlSytnzpwqVKiQqlSpoq5du2rPnj3p/GoAAACSb+3atWrfvr0uuuginXHGGd4jJiZG7dq10w8//KDMbuzYsXr11Vf9nkZQ+vTTTwnuAachy+l8EQBklIkTJ6pRo0YqUKCAmjdvrhIlSuj333/XyJEj9cEHH2j8+PG67bbbkv18O3bsUOXKlbVr1y41a9bMC4Zt377dW0gOGTJEbdq0Ue7cudP1NQEAACTH1KlTdffddytLlizeTcDy5csrMjJSP/74o7dGsrWLBcrOO+88X+b3zz//eHNL70DYihUr1LFjx3T9c0I1EDZo0CCCYUAKEQgDELR+/fVX3Xvvvbrgggs0e/ZsnXXWWfHnLKPrf//7n3feglh2TXJYAO2PP/7Qt99+qyuvvDLBOQuOZcuWLc1fBwAAwOmsgxo2bOgFuWbOnKkiRYokON+3b18NHjzYC4ydzN69e5UrV650mWOOHDnS5XkBID2xNRJA0HrxxRe1b98+DRs2LEEQzJx55pl64403vMVdv379UrSojIqK0hVXXHHcubx587KgAwAAQcHWN7bOeeutt44LghnLxOrQoYOKFSuWoI6XZbbbeqdu3brKkyePl0lmvvnmG915550qXry4V2rCvu6RRx7xsroSmzx5ssqWLeuti+zjpEmTkl13a+PGjV7W/dlnn+39OZdcconefPPNBNd89dVX3te+//77eu6553Tuued6f1aNGjW0Zs2a+OuuvfZaffLJJ1q3bp13vT0S1ylL7MCBA97rsrWjvf5bbrlFGzZsSPLa5MzVDBw40Dtn21Lz58/v7S6wTLXEz2W7F6yEhz2X7WKwnQYHDx6Mv2bnzp1eZpu993bNhRde6AU0jx49Gn+N7Xyw1/nSSy95a+CSJUt6115++eVauHBhgr9rywaL+3uIewA4NTLCAAStKVOmeIsdy/xKytVXX+2dtwVSctld1SNHjujdd99V06ZN03C2AAAAabst0gIlVatWTdHXHT58WLVq1VL16tW9YIoFb8yECRO8G4wWnClYsKAWLFjgBXgsSGTn4nzxxRdq0KCBV4esT58+XgmJBx54wAtWncrWrVu9m40WkLG6ZhaM+uyzz7wAkWXeJ97e+MILL3gZbY8++qhiY2O94J8F7ubPn++df/LJJ73jNsf+/ft7x05VwqJFixYaPXq07rnnHi/7f9asWbrppptOe67Dhw/3Ao533HGHtyNh//793m4Em6P9GWbTpk1evVkLdLVq1corvWGBMSvjYe+57Tiwj9dcc413/MEHH/QCkt999526deumzZs3H1cHzQJtu3fv9q61Odp7c/vtt+u3335T1qxZveP2506fPt1b1wJIgQAABKGdO3cG7EdU/fr1T3rdLbfc4l23a9euwFtvveV9vnDhwhNev2XLlsBZZ53lXVe6dOlA69atA2PHjvX+PAAAgGAQGxvrrVVuvfXW4879/fffgT///DP+sW/fvvhzTZs29b7u8ccfP+7rjr0uTp8+fQIRERGBdevWxR+rUKFCoEiRIgnWRl988YX3vOedd16Cr7djPXv2jB83b97c+9q//vorwXUNGzYMREdHx8/hyy+/9L62TJkygQMHDsRf99prr3nHly9fHn/spptuOu7PPZGlS5d6X9+2bdsEx++5557TnqutRS+55JKT/rn33XdfIDIyMsk16NGjR72Pzz77bCBXrlyBn3/+OcF5+7uKiooK/PHHH9547dq13lwLFiwY2LFjR/x1H330kXd8ypQp8cfatWvnHQOQMmyNBBCU7A6YsZT2k4k7b3fuksNS35ctW6bWrVvr77//1tChQ727edY58tlnn7WVRBrMHgAA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adOmqW7dutqwYYOXaXYq/B0BAMLSgQNS167Sa6+58WWXua2QF1/s98xCRnLXEGSEAQCA4PDTT9K110rTp/s9EyTDwYMHNWzYMG/BaVlkZu7cud52yLggmLHtk5GRkcdtoQQAAMesga644r8gWMeOrkg+QbB0QbF8AADgr0OHXAekZ591d0M7d5aWLUvXzDCcPtvu2LBhQ+3bt09FihTxtkCeeeaZ3rktW7aoUKFCCa7PkiWLChQo4J1LyoEDB7zHsXdzAQAINUeOBrRg7Q5t271fhfLkUJUSBRQVGXHqTPi335bat7f6BJL9Ph01SrrppoyadlgiEAYAAPyzcKHUvLm0fLkb164tDR1KECyIXXfddVq6dKn++usvDR8+XHfddZeX7ZU4AJZcffr0Ua9evdJ8ngAAZJRpKzar15RV2hy7P/5Ykegc6lkvRrXLFkn6i+zGT+vWbvujuf566d13pWSUEUDqsDUSAABkPLvraZlftg3AgmAFC0qjR0uffiqdd57fs8NJWMfICy+8UFdccYVGjhzpZXzZR1O4cGFt27YtwfWHDx/2OknauaR069bNq+UR91i/fn2GvA4AANIqCNZm9JIEQTCzJXa/d9zOH2fBAqlCBRcEi4qSnn9e+uILgmAZhEAYAADIWLbQK1tWeuUV6ehRqUkTafVqazdIJlgIOnr0aPzWxmrVqmnnzp1avHhx/PlZs2Z511StWjXJr8+ePbtX0PbYBwAAobId0jLBkupAGHfMztt1Hlv3WDmIq66S1q51N/+++cbuCrmAGDIEWyMBAEDG2L7dZYFZLQxTvLj0xhtuOySCwp49e7RmzZr48dq1a71tkFbjq2DBgnruued0yy23eLXBbGvkoEGDtHHjRt15553e9WXKlFHt2rXVsmVLDR06VIcOHVL79u29mmLJ6RgJAEAosZpgiTPBjmXhLztv11XLdUi6915pxgx38q673DooX76MmzA8ZIQBAID0ZYVgx4+3KIkLglnW18MPSytXEgQLMosWLdJll13mPUynTp28z3v06KGoqCj9+OOPatCggS666CLVq1dP27dv1zfffKNLLrkk/jnGjBmj0qVLq0aNGqpbt66qV6/udZcEACCzscL4yTLtM+nSS10QLGdOacQItzYiCOYLMsIAAED6sXpPbdtaq0E3toCJLf6sNhiCzrXXXquABS5PYOLE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lhEWrsEwfs6HeVmKzp2lIUPc2LpDjhsnlSzp98wAINMhEAaEMwt8tW8vTZzoxhddJA0fLl19td8zQxLsH0PVShb0exoAwlzJkiX19ddfa+/evV7QyrpD3n333brgggtUuHBh75qtW7d6x+PYuEKFCkk+X/bs2b0H+DkftlaulBo2lFascGNrStS7t5Qtm98zA4BMia2RQDgKBFzx+5gYFwSzDpBWHN9acRMEAwAkg3WDtGDX33//rc8//9wrjl+iRAkvGDZz5sz46yxYZt0jbUslgETrsWHDXPaXBcFsS/Hnn1vrVYJgAJCOyAgDws2aNVKrVtKXX7qxdYYcMcLVowAA4BQs6GXdIS+++GKtWbNGXbp0UenSpfXAAw8oIiJCHTt2VO/evVWqVCkvMNa9e3cVLVpUt956q99TB4LH33+79dgHH7hxrVrS22+7YBgAIF0RCAPCqQ33yy+7Vtz791uLL5d236GDywgDACAZYmNjvbpeGzZsUIECBdSgQQM999xzypo1q3f+scce87ZNtmrVSjt37lT16tU1bdq04zpNAmHru++kRo2kP/5wazDr1G118iLZrAMAGSEiYLf0Qoyl2FtXIVuI5c2b1+/pAMHPWm63aCF9/70b33CDNHSodMEFfs8MADIUa4jgx98RMq0jR1zQy25K2udWCN8K4tvWSABAhq0huO0AZGb79kldu0pVqrggWP78rgW31Z8gCAYAAJAxNm6UataUund3QbDGjd2NSoJgAJDh2A8FZFazZrnaE7/+6sZ33y299hq1JwAAADLSxx9LDzwg7dhhXSakwYOl++7ze1YAELYIhAGZsfjqo49Kb77pxuee6xZc9er5PTMAAICQdeRoQAvW7tC23ftVKE8OVSlRQFGRESf+AqvJ+thj0sCBblyxotsKedFFGTZnAMDxCIQBmYWV+/vwQ6l9e2nrVnesXTvp+eclaqwAAACctmkrNqvXlFXaHLs//liR6BzqWS9GtcsWOf4LfvxRathQWrbMja0Yvq3JsmfPwFkDAJJCjTAgs9SduO026c47XRCsdGlpzhzp9dcJggEAAKQyCNZm9JIEQTCzJXa/d9zOJ7gxOXKkVKmSC4KddZb0ySeuczdBMAAICgTCgFB29Kj0xhtSTIz00UeuBbcVYV26VLrqqnTZEjD31+36aOlG76ONAQAAMitb61gmWFIr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lV5++WXlz58//pp+/fppwIABGjp0qObPn69cuXKpVq1a3jc55P0iOvZ7b/r06d7xO++80/vI99/J9e3bV0OGDNHrr7+u1atXe2P7nhs4cGD8NXwPnlyLFi2877t3331Xy5cv935B2S92+4eP4f37z969e1W+fHkNGjQoyfPJea9scbRy5UrvPZ86daq3aGjVqpXCwanePztfvXp17//jE+FnIk4H67zTx1ovdVjnpQ7rvNRjnZd8rPPCcJ0XCGM9e/YMlC9fPslzO3fuDGTNmjUwYcKE+GOrV6+2WxCBuXPnBsJd165dA9WrVz/h+aNHjwYKFy4cePHFFxO8p9mzZw+MGzcug2YZWh5++OFAyZIlvfeO779Tu+mmmwLNmjVLcOz2228PNG7c2Puc78GT27dvXyAqKiowderUBMcrVqwYePLJJ3n/TsL+P5w0aVL8ODnv1apVq7yvW7hwYfw1n332WSAiIiKwcePGQDi/f8dau3atd/77779PcJyfiTgdrPNSh7Ve2mKdlzKs81KHdd7pY50XHuu8sM8Is5RGS+G74IILvCjuH3/84R1fvHixDh065EXN41g6ffHixTV37lyFu48//liVK1f27moVKlRIl112mYYPHx5/fu3atdqyZUuC9y86OlpVq1bl/UvCwYMHNXr0aDVr1sxLF+X779QsvXvmzJn6+eefvfGyZcu8O/116tTxxnwPntzhw4e9bQc5cuRIcNzSve195P1LvuS8V/bR0uTt52Ycuz4yMtK7s4iT42ciThfrvNPHWi/tsM5LOdZ5qcM6L+2wzkt/fvxMDOtAmH3zjho1StOmTfNSb+2b/H//+5+3n9q+2bNly+Z9Qx/r7LPP9s6Fu99++817z0qVKqXPP/9cbdq0UYcOHfT222975+PeI3u/jsX7lzTbR71z507df//93pjvv1N7/PHH1bBhQ++HpG3bsAW61UGwf+gYvgdPLk+ePKpWrZpXb8NSj22xZIt0+2VjWzh4/5IvOe+VfbR/SB4rS5YsKlCgAO9nMvAzEaeDdV7qsNZLO6zzUo51Xuqwzks7rPPSnx8/E7MojMXdUTCXXnqpt2CyYoLvv/++Fy3HiR09etSLeD///PPe2H45rVixwts33bRpU7+nF3JGjhzpfT/aXWskj/1/OmbMGI0dO9arAWNFF22BZO8h34PJYzUj7O70Oeeco6ioKFWsWFGNGjXy7soAQKhjnZc6rPXSDuu8lGOdl3qs84ATC+uMsMQsAnnRRRdpzZo1Kly4sJfGbHdvjmWdC+xcuLOOGTExMQmOlSlTJn7LQdx7lLjTA+/f8datW6cZM2Z4BS3j8P13al26dIm/W2hdrO69916vyGKfPn2883wPnpp1YLJilNbRZv369VqwYIGXlmxbiHj/ki8575V93LZt23HbFqzDEO/nqfEzEWmBdV7KsNZLG6zzTg/rvNRjnZc2WOelPz9+JhIIO4b9kPj111+9X/yVKlXy0nBtb3qcn376yfvlb2mm4c66CNn7cSzbw293Wo21OrZv2mPfv127dnl7pHn/Enrrrbe8VNqbbrop/hjff6e2b98+b9/9sexul93BNnwPJp91vrGfe9YhzLa/1K9fn/cvBZLzXtlH++V+7F3YWbNmed+vlqWCk+NnItIC67yUYa2XNljnnR7WeWmHdV7qsM5Lf778TAyEsc6dOwe++uorr3vBt99+G6hZs2bgzDPPDGzbts0737p160Dx4sUDs2bNCixatChQrVo174FAYMGCBYEsWbIEnnvuucAvv/wSGDNmTOCMM84IjB49Ov6aF154IZAvX77ARx99FPjhhx8C9evXD5QoUSLwzz//+Dr3YHLkyBHve8w6MyXG99/JNW3aNHDOOed43XDs/+GJEyd6//8+9thj8dfwPXhy06ZN8zra/Pbbb4EvvvjC665WtWrVwMGDB73zvH//2b17t9fhxh72q/OVV17xPl+3bl2y36vatWsHLrvsssD8+fMDc+bMCZQqVSrQqFGjQDg41fu3fft2b/zJJ59458ePH++NN2/eHP8c/ExESrHOSx3WeqnHOu/0sc5LPdZ5ycc6L/zWeWEdCLv77rsDRYoUCWTLls37QWvjNWvWxJ+3b+y2bdsG8ufP7/3iv+222xL8ZYW7KVOmBMqWLeu1ji1dunRg2LBhCc5bq9nu3bsHzj77bO+aGjVqBH766Sff5huMPv/8c++HQVLvC99/J7dr1y6vFbn9wMyRI0fgggsu8NpBHzhwIP4avgdP7r333vPeN/sZaG2h27Vr57UvjsP7958vv/zS+3818cMW6sl9r2wRYAui3LlzB/LmzRt44IEHvIVDODjV+/fWW28leb5nz57xz8HPRKQU67zUY62XOqzzTh/rvNRjnZd8rPPCb50XYf9Jn1wzAAAAAAAAIHhQIwwAAAAAAABhgUAYAAAAAAAAwgKBMAAAAAAAAIQFAmEAAAAAAAAICwTCAAAAAAAAEBYIhAEAAAAAACAsEAgDAAAAAABAWCAQBgAAAAAAgLBAIAwAAAAAAABhgUAYAAAAAAAAwgKBMAAAAAAAAIQFAmEAAAAAAABQOPg/yMiNV8Vew38AAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 1500x500 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from matplotlib import pyplot as plt\n",
    "\n",
    "%matplotlib inline\n",
    "\n",
    "fig, axes = plt.subplots(1, 2, figsize=(15, 5))\n",
    "\n",
    "axes[0].scatter(x, y)\n",
    "axes[0].plot(np.array([50, 110]), np.array([50, 110]) * w1 + w0, \"r\")\n",
    "axes[0].set_title(\"OLS\")\n",
    "axes[1].scatter(x, y)\n",
    "axes[1].plot(np.array([50, 110]), np.array([50, 110]) * w1_ + w0_, \"r\")\n",
    "axes[1].set_title(\"Gradient descent\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fc3afe68",
   "metadata": {},
   "source": [
    "### ------------------下面是代码解析1-----------------------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "98b0eda7",
   "metadata": {},
   "source": [
    "这段代码使用 Matplotlib 绘制了两个子图，分别展示了 **普通最小二乘法 (OLS)** 和 **梯度下降法** 的线性回归拟合效果。以下是逐行解读：\n",
    "\n",
    "---\n",
    "\n",
    "### 1. **导入 Matplotlib**\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3404624f",
   "metadata": {},
   "source": [
    "from matplotlib import pyplot as plt\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7af9c346",
   "metadata": {},
   "source": [
    "- **`from matplotlib import pyplot as plt`**：导入 Matplotlib 的绘图模块 `pyplot`，用于绘制图形。\n",
    "- **`%matplotlib inline`**：这是 Jupyter Notebook 的魔法命令，用于在 Notebook 中直接显示绘图结果。\n",
    "\n",
    "---\n",
    "\n",
    "### 2. **创建子图**\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "405ab795",
   "metadata": {},
   "source": [
    "fig, axes = plt.subplots(1, 2, figsize=(15, 5))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a859b7c9",
   "metadata": {},
   "source": [
    "- **`plt.subplots(1, 2, figsize=(15, 5))`**：\n",
    "  - 创建一个包含 1 行 2 列的子图布局。\n",
    "  - **`fig`**：表示整个图形对象。\n",
    "  - **`axes`**：是一个包含两个子图的数组，分别对应两个子图。\n",
    "  - **`figsize=(15, 5)`**：设置整个图形的宽度为 15 英寸，高度为 5 英寸。\n",
    "\n",
    "---\n",
    "\n",
    "### 3. **绘制第一个子图 (OLS)**\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6e0c17d0",
   "metadata": {},
   "source": [
    "axes[0].scatter(x, y)\n",
    "axes[0].plot(np.array([50, 110]), np.array([50, 110]) * w1 + w0, \"r\")\n",
    "axes[0].set_title(\"OLS\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e6bb01e2",
   "metadata": {},
   "source": [
    "- **`axes[0].scatter(x, y)`**：\n",
    "  - 在第一个子图中绘制散点图。\n",
    "  - **`x`** 和 **`y`** 是数据点的横纵坐标，表示样本数据的分布。\n",
    "- **`axes[0].plot(np.array([50, 110]), np.array([50, 110]) * w1 + w0, \"r\")`**：\n",
    "  - 在第一个子图中绘制回归直线。\n",
    "  - **`np.array([50, 110])`**：指定直线的横坐标范围为 50 到 110。\n",
    "  - **`np.array([50, 110]) * w1 + w0`**：根据线性回归模型 \\( y = w_1 x + w_0 \\) 计算对应的纵坐标。\n",
    "  - **`\"r\"`**：设置直线颜色为红色。\n",
    "- **`axes[0].set_title(\"OLS\")`**：\n",
    "  - 设置第一个子图的标题为 \"OLS\"（普通最小二乘法）。\n",
    "\n",
    "---\n",
    "\n",
    "### 4. **绘制第二个子图 (梯度下降)**\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a9787518",
   "metadata": {},
   "source": [
    "axes[1].scatter(x, y)\n",
    "axes[1].plot(np.array([50, 110]), np.array([50, 110]) * w1_ + w0_, \"r\")\n",
    "axes[1].set_title(\"Gradient descent\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b6a26c73",
   "metadata": {},
   "source": [
    "- **`axes[1].scatter(x, y)`**：\n",
    "  - 在第二个子图中绘制散点图，与第一个子图相同。\n",
    "- **`axes[1].plot(np.array([50, 110]), np.array([50, 110]) * w1_ + w0_, \"r\")`**：\n",
    "  - 在第二个子图中绘制回归直线。\n",
    "  - **`w1_`** 和 **`w0_`** 是通过梯度下降法计算得到的模型参数。\n",
    "  - 直线公式为 \\( y = w_1' x + w_0' \\)。\n",
    "- **`axes[1].set_title(\"Gradient descent\")`**：\n",
    "  - 设置第二个子图的标题为 \"Gradient descent\"（梯度下降法）。\n",
    "\n",
    "---\n",
    "\n",
    "### 5. **总结**\n",
    "- **第一个子图 (OLS)**：\n",
    "  - 使用普通最小二乘法计算的模型参数 \\( w_1 \\) 和 \\( w_0 \\) 绘制回归直线。\n",
    "- **第二个子图 (梯度下降)**：\n",
    "  - 使用梯度下降法计算的模型参数 \\( w_1' \\) 和 \\( w_0' \\) 绘制回归直线。\n",
    "- **对比**：\n",
    "  - 两个子图展示了两种方法的拟合效果，通常两者的结果应该非常接近（如果梯度下降法收敛良好）。\n",
    "\n",
    "这段代码的目的是直观展示两种方法在同一数据集上的拟合效果，便于对比理解。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b27f7781",
   "metadata": {},
   "source": [
    "### ------------------上面是代码解析1-----------------------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d21c0e66",
   "metadata": {},
   "source": [
    "可以看出，图像显示的结果还是非常接近的。 \n",
    "\n",
    "线性回归方法之所以使用普通最小二乘法来求解，是因为我们可以很方便地求出损失函数的最小值。但是，机器学习中的很多问题，往往会面对非常复杂的损失函数，这些损失函数一般无法直接求得最小值，只能使用迭代方法来求取局部或全局极小值。这也就是我们学习梯度下降等迭代方法的原因。 "
   ]
  }
 ],
 "metadata": {
  "jupytext": {
   "cell_metadata_filter": "-all",
   "main_language": "python",
   "notebook_metadata_filter": "-all"
  },
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
